package com.xqkj.commons.virtualdb.templates.impl;

import com.xqkj.commons.constant.HandleResultCode;
import com.xqkj.commons.model.HandleResult;
import com.xqkj.commons.model.basicdo.BasicDo;
import com.xqkj.commons.virtualdb.model.*;
import com.xqkj.commons.virtualdb.service.functions.*;
import com.xqkj.commons.virtualdb.templates.UpdateAttributeToVirtualDb;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * @author lwt<br>
 * @description <br>
 * @date 2020/1/16
 */
public class DefUpdateAttributeToVirtualDb extends BasicUpdateModelToVirtualDb<ModelBasicAttributeSvModel>
        implements UpdateAttributeToVirtualDb {

    private Function<ModelBasicAttributeSvModel,HandleResult<Integer>> attributeUpdateFunction;
    private Function<UnionIdxMappingSvModel,Integer> delOldAndInsertNewUidxMappingFunction;
    private Function<GetByUnionIdxParameterModel,BasicDo> getByAttributeUidxFunction;
    private Function<String,Boolean> lockFunction;
    private Consumer<String> unLockFunction;
    private Function<ModelAttributePkAndShadingInfoModel,ModelBasicAttributeSvModel> shadingKeysQueryAttributeFunction;
    //
    private Function<ParametersWrappedModel<BasicDo>,VirtualDbLockInfoModel> lockInfoGetter;
    private Function<VirtualDbLockInfoModel, HandleResult<BasicDo>> dbModelGetter;
    private Function<VirtualDbLockInfoModel, VirtualDbLockResultModel> lockAllFunction;
    private Consumer<VirtualDbLockInfoModel> unLockAllFunction;
    private Function<VirtualDbLockInfoModel,HandleResult<String>> unionTmpMappingWriter;
    //
    private OperateModelToVirtualDbHelper<BasicDo> operateModelToVirtualDbHelper;
    //
    private boolean isInit=false;

    public DefUpdateAttributeToVirtualDb(){

    }

    public void init(){
        if(isInit){
            return;
        }
        lockInfoGetter=new LockInfoGetter<>();
        unionTmpMappingWriter=new UnionTmpMappingWriter(delOldAndInsertNewUidxMappingFunction,null);
        dbModelGetter=new DbModelGetter<>(null,getByAttributeUidxFunction);
        lockAllFunction=new LockAllFunction(lockFunction);
        unLockAllFunction=new UnLockAllFunction(unLockFunction);
        //
        operateModelToVirtualDbHelper=new OperateModelToVirtualDbHelper();
        operateModelToVirtualDbHelper.setDbModelGetter(dbModelGetter);
        operateModelToVirtualDbHelper.setLockAllFunction(lockAllFunction);
        operateModelToVirtualDbHelper.setUnLockAllFunction(unLockAllFunction);
        isInit=true;
    }

    @Override
    public HandleResult<Integer> updateModelAttribute(ModelBasicAttributeSvModel modelAttribute, Long tenantId, String tenantExtCode, VirtualDbAttributeIdxConfigModel attributeIdxConfig) {
        ModelAttributePkAndShadingInfoModel parameterModel=new ModelAttributePkAndShadingInfoModel();
        parameterModel.setPkId(modelAttribute.getPkId());
        parameterModel.setParentPkId(modelAttribute.getParentPkId());
        parameterModel.setTenantId(tenantId);
        ModelBasicAttributeSvModel dbModelAttribute=shadingKeysQueryAttributeFunction.apply(parameterModel);
        if(dbModelAttribute==null){
            return HandleResult.failed(HandleResultCode.DATA_NOT_EXISTED.getCode(),HandleResultCode.DATA_NOT_EXISTED.getDesc());
        }
        //
        ParametersWrappedModel<BasicDo> parametersWrappedModel=new ParametersWrappedModel<>();
        parametersWrappedModel.setTenantId(tenantId);
        parametersWrappedModel.setTenantExtCode(tenantExtCode);
        parametersWrappedModel.setAttributeIdxConfig(attributeIdxConfig);
        Map<String,ModelBasicAttributeSvModel> codeToAttributeMap=new HashMap<>();
        codeToAttributeMap.put(modelAttribute.getAttributeCode(),modelAttribute);
        parametersWrappedModel.setCodeToAttributeMap(codeToAttributeMap);
        //
        VirtualDbLockInfoModel virtualDbLockInfoModel = lockInfoGetter.apply(parametersWrappedModel);
        if(!virtualDbLockInfoModel.isNeedLock()){
            return doUpdateModel(modelAttribute);
        }
        //
        return operateModelToVirtualDbHelper.lockAddMappingAndExecuteOperation(
                parametersWrappedModel,virtualDbLockInfoModel,
                (parametersWrapped,virtualDbLockInfo)
                        ->handleUnionTmpMapping(parametersWrapped,virtualDbLockInfoModel),
                (parametersWrapped)
                        ->doUpdateModel(modelAttribute));
    }

    @Override
    protected HandleResult<Integer> doUpdateModel(ModelBasicAttributeSvModel model) {
        return attributeUpdateFunction.apply(model);
    }

    private HandleResult<String> handleUnionTmpMapping(ParametersWrappedModel<BasicDo> parametersWrapped,
                                                       VirtualDbLockInfoModel virtualDbLockInfoModel) {
        return unionTmpMappingWriter.apply(virtualDbLockInfoModel);
    }

    //////////////////////////////////////
    public void setAttributeUpdateFunction(Function<ModelBasicAttributeSvModel, HandleResult<Integer>> attributeUpdateFunction) {
        this.attributeUpdateFunction = attributeUpdateFunction;
    }

    public void setDelOldAndInsertNewUidxMappingFunction(Function<UnionIdxMappingSvModel, Integer> delOldAndInsertNewUidxMappingFunction) {
        this.delOldAndInsertNewUidxMappingFunction = delOldAndInsertNewUidxMappingFunction;
    }

    public void setGetByAttributeUidxFunction(Function<GetByUnionIdxParameterModel, BasicDo> getByAttributeUidxFunction) {
        this.getByAttributeUidxFunction = getByAttributeUidxFunction;
    }

    public void setLockFunction(Function<String, Boolean> lockFunction) {
        this.lockFunction = lockFunction;
    }

    public void setUnLockFunction(Consumer<String> unLockFunction) {
        this.unLockFunction = unLockFunction;
    }

    public void setShadingKeysQueryAttributeFunction(Function<ModelAttributePkAndShadingInfoModel, ModelBasicAttributeSvModel> shadingKeysQueryAttributeFunction) {
        this.shadingKeysQueryAttributeFunction = shadingKeysQueryAttributeFunction;
    }
}
